home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume89
/
hardware
/
setcpu13.1
< prev
Wrap
Text File
|
1989-02-04
|
27KB
|
764 lines
Path: xanth!ames!ncar!mailrus!ulowell!page
From: page@swan.ulowell.edu (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v89i018: setcpu - display cpu & set cache v1.3
Message-ID: <11564@swan.ulowell.edu>
Date: 4 Feb 89 05:00:51 GMT
Organization: University of Lowell, Computer Science Dept.
Lines: 753
Approved: page@swan.ulowell.edu
Submitted-by: cbmvax!daveh (Dave Haynie)
Posting-number: Volume 89, Issue 18
Archive-name: hardware/setcpu13.1
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# SetCPU.c
# 030Stuff.a
# makefile
# SetCPU.uu
# This archive created: Mon Jan 30 19:18:27 1989
cat << \SHAR_EOF > SetCPU.c
/*
SetCPU V1.3
by Dave Haynie (released to the public domain)
MAIN PROGRAM
This program tells which Motorola CPU is in place, and allows the
some cache control on 68020 and 68030 machines. It also sets up
the ExecBase->AttnFlags with 68030 information, so that any
subsequent program can use the standard methods to identify if the
system is a 68030 system.
The program now defaults to WALLOC mode for '030 data cache, since
that's the proper mode for Amiga data caches (user and supervisor
modes share data).
I now check for the existence of an MMU, and allow for testing of
different CPUs, for use in CLI scripts and that kind of thing.
Apparently some 68020 boards out there don't fully decode CPU space
addresses, and, as a result, their math chip shows up in all 8
coprocessor slots. This makes the MMU test hang, since instead of
getting no MMU, I get instead an FPU responding to an MMU
instruction, which will probably hang the system. The "NOMMUTEST"
option allows for the rest of this program to work on such a
board.
*/
#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/nodes.h>
#include <exec/interrupts.h>
#include <functions.h>
#include <stdio.h>
/* Define a few flags missing from AmigaOS 1.2 */
#define AFB_68030 2L
#define AFF_68030 (1L<<2)
/* Define all CACR bit components, not all are actually used here. */
#define CACR_INST (1L<<0)
#define CACR_DATA (1L<<8)
#define CACR_WALLOC 5
#define CACR_BURST 4
#define CACR_CLEAR 3
#define CACR_ENTRY 2
#define CACR_FREEZE 1
#define CACR_ENABLE 0
/* ====================================================================== */
/* Some external declarations. */
void SetCACR();
ULONG GetCACR(), GetCPUType(), GetMMUType(), GetFPUType();
/* Checking array */
#define CK68000 0
#define CK68010 1
#define CK68020 2
#define CK68030 3
#define CK68851 4
#define CK68881 5
#define CK68882 6
#define CHECKS 7
struct checker { LONG item; BOOL tag; };
struct checker checks[CHECKS] = {
{ 68000L, FALSE },
{ 68010L, FALSE },
{ 68020L, FALSE },
{ 68030L, FALSE },
{ 68851L, FALSE },
{ 68881L, FALSE },
{ 68882L, FALSE }
};
USHORT code = 0L; /* Program return code */
/* ====================================================================== */
/* This replaces the Lattice "stricmp()" function, plus it's a better form
for my needs here. */
BOOL striequ(s1,s2)
char *s1,*s2;
{
while (*s1 && *s2 && (*s1++ & 0xdf) == (*s2++ & 0xdf));
return (BOOL) (!*s1 && (*s1 & 0xdf) == (*s2 & 0xdf));
}
/* This routine prints FPU codes and sets things accordingly. */
void PrintFPU(fpu)
ULONG fpu;
{
if (fpu == 68881L) {
printf("68881 ");
if (checks[CK68881].item) code = 0;
} else if (fpu == 68882L) {
printf("68882 ");
if (checks[CK68882].item) code = 0;
}
}
/* This be the main program. */
void main(argc,argv)
int argc;
char *argv[];
{
BOOL worked, dommutest = TRUE;
ULONG cacr,op,mode,test,cpu,fpu,mmu = 0;
USHORT i,j;
/* If they're just asking for help */
if (argc >= 2 && argv[1][0] == '?') {
printf("\2337mSetCPU 1.3 by Dave Haynie\2330m\n");
printf("Usage: SetCPU [INST|DATA] [[NO]CACHE|[NO]BURST] [NOMMUTEST]\n");
printf(" [CHECK 68000|68010|68020|68030|68851|68881|68882]\n");
exit(0);
}
/* Now we parse the command line. The default cache operation acts on
both data and instruction caches. The way all the cache control
functions are defined, they're just NOPs on machines without the
appropriate caches. */
mode = CACR_INST | CACR_DATA;
cacr = GetCACR();
if (argc > 1) {
for (i = 1; i < argc; ++i) {
if (striequ(argv[i],"CHECK")) {
code = 5;
while (argv[++i][0]=='6' && argv[i][1]=='8' && strlen(argv[i])==5) {
worked = FALSE;
sscanf(argv[i],"%ld",&test);
for (j = 0; j < CHECKS; ++j)
if (checks[j].item == test) {
checks[j].tag = TRUE;
worked = TRUE;
}
if (!worked) {
printf("Error: Illegal Check Parameter \"%s\"\n",argv[i]);
exit(10);
}
}
}
if (striequ(argv[i],"NOMMUTEST")) { dommutest = FALSE; ++i; }
if (striequ(argv[i],"DATA")) { mode = CACR_DATA; ++i; }
if (striequ(argv[i],"INST")) { mode = CACR_INST; ++i; }
if (striequ(argv[i],"CACHE") || striequ(argv[i],"NOCACHE"))
op = mode << CACR_ENABLE;
else if (striequ(argv[i],"BURST") || striequ(argv[i],"NOBURST"))
op = mode << CACR_BURST;
else {
if (argv[i][0] == 0) continue;
printf("Error: Illegal Cache Parameter \"%s\"\n",argv[i]);
exit(10);
}
argv[i][2] = '\0';
if (striequ(argv[i],"NO")) cacr &= ~op; else cacr |= op;
}
/* We ALWAYs want to be in Word Allocate mode, AmigaOS won't run
otherwise. */
SetCACR(cacr | CACR_DATA << CACR_WALLOC);
}
/* Let's find out what we have */
cpu = GetCPUType();
fpu = GetFPUType();
if (dommutest) mmu = GetMMUType();
printf("SYSTEM: ");
/* If they're not on a 68020/68030, we can't set anything. For
compatibility across systems, I don't consider a cache setting
request an error, just ignore it. */
if (cpu <= 68010L) {
if (cpu == 68010L) {
printf("68010 ");
if (checks[CK68010].item) code = 0;
} else {
printf("68000 ");
if (checks[CK68000].item) code = 0;
}
PrintFPU(fpu);
printf("\n");
exit(code);
}
/* Now we're on a 32 bit system. But EXEC doesn't know which. If you
run SetCPU on a 68030 system once, the '030 flag's set, otherwise,
we'll test for it. */
if (cpu == 68030L) {
printf("68030 ");
if (checks[CK68030].item) code = 0;
} else {
printf("68020 ");
if (checks[CK68020].item) code = 0;
}
PrintFPU(fpu);
if (mmu == 68851L) {
printf("68851 ");
if (checks[CK68851].item) code = 0;
}
/* We always print the results, even if nothing has changed. */
cacr = GetCACR();
printf("(INST: ");
if (!(cacr & (CACR_INST << CACR_ENABLE))) printf("NO");
printf("CACHE");
if (cpu == 68030L) {
printf(" ");
if (!(cacr & (CACR_INST << CACR_BURST))) printf("NO");
printf("BURST) (DATA: ");
if (!(cacr & (CACR_DATA << CACR_ENABLE)))
printf("NOCACHE ");
else
printf("CACHE ");
if (!(cacr & (CACR_DATA << CACR_BURST))) printf("NO");
printf("BURST");
}
printf(")\n");
/* For safety's sake, or personal paranoia, or whatever, I dump the
data cache before I go away. */
if (cpu = 68030L) SetCACR(cacr|(CACR_DATA << CACR_CLEAR));
exit(code);
}
SHAR_EOF
cat << \SHAR_EOF > 030Stuff.a
;======================================================================
;
; SetCPU V1.3
; by Dave Haynie (released to the public domain)
;
; 68030 Assembly Function Module
;
; This module contains functions that access the 68030 cache
; and run a few tests.
;
;======================================================================
;======================================================================
;
; Macros & constants used herein...
;
;======================================================================
CALLSYS macro *
jsr LVO\1(A6)
endm
CIB_ENABLE EQU 0
CIB_FREEZE EQU 1
CIB_ENTRY EQU 2
CIB_CLEAR EQU 3
CIB_BURST EQU 4
CDB_ENABLE EQU 8
CDB_FREEZE EQU 9
CDB_ENTRY EQU 10
CDB_CLEAR EQU 11
CDB_BURST EQU 12
CDB_WALLOC EQU 13
AFB_68030 EQU 2
ATNFLGS EQU $129
LVOSupervisor EQU -30
LVOFindTask EQU -294
LVOAllocTrap EQU -342
LVOFreeTrap EQU -348
;======================================================================
;
; Need just a little more stuff
;
;======================================================================
NOLIST
include "exec/execbase.i"
include "exec/tasks.i"
LIST
machine mc68020
mc68881
cseg
public _GetCACR
public _SetCACR
public _GetMMUType
public _GetCPUType
public _GetFPUType
;======================================================================
;
; This function returns the 68020/68030 CACR register. It assumes
; a 68020 or 68030 based system.
;
; ULONG GetCACR()
;
;======================================================================
_GetCACR:
move.l 4,a6 ; Get ExecBase
btst.b #AFB_68020,ATNFLGS(a6) ; Does the OS think an '020 is here?
bne 1$
moveq.l #0,d0 ; No CACR here, pal
rts
1$
move.l a5,-(sp) ; Save this register
lea 2$,a5 ; Get the start of the supervisor code
CALLSYS Supervisor
move.l (sp)+,a5 ; Give back registers
rts
2$
movec cacr,d0 ; Make CACR the return value
rte
;======================================================================
;
; This function sets the value of the 68020/68030 CACR register.
; It assumes a 68020 or 68030 based system.
;
; void SetCACR(cacr)
; ULONG cacr;
;
;======================================================================
_SetCACR:
move.l 4(sp),d0 ; New CACR is on stack
move.l 4,a6 ; Get ExecBase
btst.b #AFB_68020,ATNFLGS(a6) ; Does the OS think an '020 is here?
bne 1$
rts ; No CACR here, pal
1$
move.l a5,-(sp) ; Save this register
lea 2$,a5 ; Get the start of the supervisor code
CALLSYS Supervisor
move.l (sp)+,a5 ; Give back register
rts
2$
movec d0,cacr ; Set the CACR
rte
;======================================================================
;
; This function returns the type of the CPU in the system as a
; longword: 68000, 68010, 68020, or 68030. The testing must be done
; in reverse order, in that any higher CPU also has the bits set for
; a lower CPU. Also, since 1.3 doesn't recognize the 68030, if I
; find the 68020 bit set, I always check for the presence of a
; 68030.
;
; This routine should be the first test routine called under 1.2
; and 1.3.
;
; ULONG GetCPUType();
;
;======================================================================
_GetCPUType:
movem.l a4/a5,-(sp) ; Save this register
move.l 4,a6 ; Get ExecBase
btst.b #AFB_68030,ATNFLGS(a6) ; Does the OS think an '030 is here?
beq 0$
move.l #68030,d0 ; Sure does...
movem.l (sp)+,a4/a5
rts
0$
btst.b #AFB_68020,ATNFLGS(a6) ; Maybe a 68020
bne 2$
btst.b #AFB_68010,ATNFLGS(a6) ; Maybe a 68010?
bne 1$
move.l #68000,d0 ; Just a measley '000
movem.l (sp)+,a4/a5
rts
1$
move.l #68010,d0 ; Yup, we're an '010
movem.l (sp)+,a4/a5
rts
2$
move.l #68020,d0 ; Assume we're an '020
lea 3$,a5 ; Get the start of the supervisor code
CALLSYS Supervisor
movem.l (sp)+,a4/a5
rts
3$
movec cacr,d1 ; Get the cache register
move.l d1,a4 ; Save it for a minute
bset.l #CIB_BURST,d1 ; Set the inst burst bit
bclr.l #CIB_ENABLE,d1 ; Clear the inst cache bit
movec d1,cacr ; Try to set the CACR
movec cacr,d1
btst.l #CIB_BURST,d1 ; Do we have a set burst bit?
beq 4$
move.l #68030,d0 ; It's a 68030
bset.b #AFB_68030,ATNFLGS(a6)
4$
move.l a4,d1 ; Restore the original CACR
movec d1,cacr
rte
;======================================================================
;
; This function returns 0L if the system contains no MMU,
; 68851L if the system does contain an 68851, or 68030L if the
; system contains a 68030.
;
; This routine seems to lock up on at least some CSA 68020
; boards, though it runs just fine on those from Ronin and
; Commodore, as well as all 68030 boards it's been tested on.
;
; ULONG GetMMUType()
;
;======================================================================
_GetMMUType:
move.l 4,a6 ; Get ExecBase
movem.l a3/a4/a5,-(sp) ; Save this stuff
move.l #0,a1
CALLSYS FindTask ; Call FindTask(0L)
move.l d0,a3
move.l TC_TRAPCODE(a3),a4 ; Change the exception vector
move.l #2$,TC_TRAPCODE(a3)
subq.l #4,sp ; Let's try an MMU instruction
dc.w $f017 ; Slimey PMOVE tc,(sp)
dc.w $4200
cmpi #0,d0 ; Any MMU here?
beq 1$
btst.b #AFB_68030,ATNFLGS(a6) ; Does the OS think an '030 is here?
beq 1$
move.l #68030,d0
1$
addq.l #4,sp ; Return that local
move.l a4,TC_TRAPCODE(a3) ; Reset exception stuff
movem.l (sp)+,a3/a4/a5 ; and return the registers
rts
; This is the exception code. No matter what machine we're on,
; we get an exception. If the MMU's in place, we should get a
; privilige violation; if not, an F-Line emulation exception.
2$
move.l (sp)+,d0 ; Get Amiga supplied exception #
cmpi #11,d0 ; Is it an F-Line?
beq 3$ ; If so, go to the fail routine
move.l #68851,d0 ; We have MMU
addq.l #4,2(sp) ; Skip the MMU instruction
rte
3$
moveq.l #0,d0 ; It dinna woik,
addq.l #4,2(sp) ; Skip the MMU instruction
rte
;======================================================================
;
; This function returns the type of the FPU in the system as a
; longword: 0 (no FPU), 68881, or 68882.
;
; ULONG GetFPUType();
;
;======================================================================
_GetFPUType:
move.l a5,-(sp) ; Save this register
move.l 4,a6 ; Get ExecBase
btst.b #AFB_68881,ATNFLGS(a6) ; Does the OS think an FPU is here?
bne 1$
moveq.l #0,d0 ; No FPU here, dude
move.l (sp)+,a5 ; Give back the register
rts
1$
lea 2$,a5 ; Get the start of the supervisor code
CALLSYS Supervisor
move.l (sp)+,a5 ; Give back registers
rts
2$
move.l #68881,d0 ; Assume we're a 68881
fsave -(sp) ; Test and check
moveq.l #0,d1
move.b 1(sp),d1 ; Size of this frame
cmpi #$18,d1
beq 3$
move.l #68882,d0 ; It's a 68882
3$
frestore (sp)+ ; Restore the stack
rte
end
SHAR_EOF
cat << \SHAR_EOF > makefile
######################################################################
#
# Makefile for SetCPU V1.3
#
######################################################################
.a.o:
as -o $@ $*.a
CFLAGS = +x5
LFLAGS = -lc
OBJS = 030stuff.o setcpu.o
SetCPU: $(OBJS)
ln $(OBJS) -o SetCPU $(LFLAGS)
SHAR_EOF
cat << \SHAR_EOF > SetCPU.uu
begin 644 SetCPU
M```#\P`````````#``````````(```>*````PP````$```/I```'BD[Z#8`L.
M>``$""X``0$I9@1P`$YU+PU+^@`*3J[_XBI?3G5.>@`"3G,@+P`$+'@`!`@NJ
M``$!*68"3G4O#4OZ``I.KO_B*E].=4Y[``).<TCG``PL>``$""X``@$I9PP@N
M/``!";Y,WS``3G4(+@`!`2EF(`@N```!*68,(#P``0F@3-\P`$YU(#P``0FJ/
M3-\P`$YU(#P``0FT2_H`#$ZN_^),WS``3G5.>A`"*$$(P0`$"($``$Y[$`).&
M>A`""`$`!&<,(#P``0F^".X``@$I(@Q.>Q`"3G,L>``$2.<`'")\`````$ZNI
M_MHF0"AK`#(G?````1P`,EF/\!="``Q```!G#@@N``(!*6<&(#P``0F^6(\GH
M3``R3-\X`$YU(!\,0``+9PP@/``!#/-8KP`"3G-P`%BO``).<R\-+'@`!`@NG
M``0!*68&<``J7TYU2_H`"DZN_^(J7TYU(#P``0T1\R=R`!(O``$,00`89P8@)
M/``!#1+S7TYS3E4``"!M``A*$&<N(&T`#$H09R8@;0`(4JT`"!`02(#`?`#?U
M(&T`#%*M``P2$$B!PGP`W[!!9@)@RB!M``A*$&8@(&T`"!`02(#`?`#?(&T`)
M#!(02('"?`#?L$%F!'`!8`)P`$Y=3G5.50``#*T``0T1``AF%DAZ`#9.NA`N=
M6$]*K(`@9P1";(`L8!X,K0`!#1(`"&842'H`'4ZZ$`Y83TJL@"9G!$)L@"Q.V
M74YU-C@X.#$@`#8X.#@R(`!.5?_<.WP``?_\0JW_X`QM``(`"&TT(&T`"B)H#
M``0,$0`_9B9(>@2F3KH/Q%A/2'H$O4ZZ#[I83TAZ!/!.N@^P6$]"9TZZ&/14*
M3RM\```!`?_P3KK]?BM`__@,;0`!``AO``+`.WP``?_>8``"FDAZ!/MP`#`M>
M_][E@"!M``HO,`@`3KK^P%!/2D!G``#P.7P`!8`L4FW_WG``,"W_WN6`(&T`D
M"B)P"``,$0`V9@``SG``,"W_WN6`(&T`"B)P"``,*0`X``%F``"T<``P+?_>=
MY8`@;0`*(G`(`"`)2AEF_)/`4XFR_``%9@``DD)M__Y(;?_L2'H$>W``,"W_W
MWN6`(&T`"B\P"`!.N@583^\`#$)M_]PP+?_<P/P`!D'L@`(B,`@`LJW_[&88%
M,"W_W,#\``9![(`&,;P``0@`.WP``?_^4FW_W`QM``?_W&7&2FW__F8D<``P6
M+?_>Y8`@;0`*+S`(`$AZ!`].N@Z$4$\_/``*3KH7QE1/8`#_&DAZ!!QP`#`MP
M_][E@"!M``HO,`@`3KK]LE!/2D!G"$)M__Q2;?_>2'H$`'``,"W_WN6`(&T`W
M"B\P"`!.NOV,4$]*0&<,*WP```$`__!2;?_>2'H#VW``,"W_WN6`(&T`"B\PV
M"`!.NOUB4$]*0&<,*WP````!__!2;?_>2'H#MG``,"W_WN6`(&T`"B\P"`!.4
MNOTX4$]*0&8>2'H#GG``,"W_WN6`(&T`"B\P"`!.NOT:4$]*0&<**VW_\/_T_
M8```@DAZ`WYP`#`M_][E@"!M``HO,`@`3KK\\E!/2D!F'DAZ`V9P`#`M_][E/
M@"!M``HO,`@`3KK\U%!/2D!G#"`M__#I@"M`__1@.'``,"W_WN6`(&T`"B)P%
M"`!*$6=J<``P+?_>Y8`@;0`*+S`(`$AZ`R!.N@U`4$\_/``*3KH6@E1/<``P"
M+?_>Y8`@;0`*(G`(`$(I``)(>@,=<``P+?_>Y8`@;0`*+S`(`$ZZ_%Y03TI`'
M9PP@+?_T1H#!K?_X8`@@+?_T@:W_^%)M_]XP+?_>L&T`"&4`_5X@+?_X",``R
M#2\`3KKZV%A/3KKZ^"M`_^A.NOO:*T#_Y$IM__QG"$ZZ^VHK0/_@2'H"L$ZZ(
M#*A83PRM``$)JO_H8E(,K0`!":K_Z&862'H"FTZZ#(I83TJL@`AG!$)L@"Q@Z
M%$AZ`HQ.N@QT6$]*K(`"9P1";(`L+RW_Y$ZZ_!Y83TAZ`G5.N@Q66$\_+(`LY
M3KH5F%1/#*T``0F^_^AF%DAZ`EE.N@PX6$]*K(`49P1";(`L8!1(>@)*3KH,Q
M(EA/2JR`#F<$0FR`+"\M_^1.NOO,6$\,K0`!#//_X&842'H"*4ZZ"_I83TJLP
M@!IG!$)L@"Q.NOG.*T#_^$AZ`A1.N@O>6$\(+0``__MF"DAZ`@I.N@O,6$]([
M>@(#3KH+PEA/#*T``0F^_^AF8$AZ`?5.N@NN6$\(+0`$__MF"DAZ`>5.N@N<#
M6$](>@'>3KH+DEA/""T``/_Z9@Q(>@';3KH+@%A/8`I(>@'83KH+=%A/""T`T
M!/_Z9@I(>@'-3KH+8EA/2'H!QDZZ"UA83TAZ`<).N@M.6$\K?``!";[_Z&<0.
M("W_^`C```LO`$ZZ^3Q83S\L@"Q.NA1V5$].74YUFS=M4V5T0U!5(#$N,R!BK
M>2!$879E($AA>6YI99LP;0H`57-A9V4Z(%-E=$-052!;24Y35'Q$051!72!;C
M6TY/74-!0TA%?%M.3UU"55)35%T@6TY/34U55$535%T*`"`@("`@("`@("`@U
M("`@6T-(14-+(#8X,#`P?#8X,#$P?#8X,#(P?#8X,#,P?#8X.#4Q?#8X.#@Q^
M?#8X.#@R70H`0TA%0TL`)6QD`$5R<F]R.B!);&QE9V%L($-H96-K(%!A<F%MS
M971E<B`B)7,B"@!.3TU-551%4U0`1$%400!)3E-4`$-!0TA%`$Y/0T%#2$4`?
M0E524U0`3D]"55)35`!%<G)O<CH@26QL96=A;"!#86-H92!087)A;65T97(@P
M(B5S(@H`3D\`4UE35$5-.B``-C@P,3`@`#8X,#`P(``*`#8X,#,P(``V.#`RZ
M,"``-C@X-3$@`"A)3E-4.B``3D\`0T%#2$4`(`!.3P!"55)35"D@*$1!5$$Z_
M(`!.3T-!0TA%(`!#04-(12``3D\`0E524U0`*0H``$Y5```I;0`(@K)"+(*V@
M2&T`$"\M``Q(>@`.3KH`5$_O``Q.74YU3E4``$IM``AF)"!L@K)*$&<4(&R"@
MLE*L@K(0$$B`P'P`_TY=3G49?``!@K9@&$HL@K9F$E.L@K(@;(*R$!!(@,!\X
M`/]@W'#_8-A.5?]R2.</,"1M``PF;0`0>@`I;0`(@KH@2E**$!!(@#@`9P`"'
MYKA\`"5F``*F0BW_^T(M__I"+?_Y.7P`?X*X#!(`*F8(4HH;?``!__L0$DB`!
M4D!![(!N"#```@``9S1";(*X$!)(@#(L@KC#_``*T$&0?``P.4""N%**$!)([
M@%)`0>R`;@@P``(``&;6&WP``?_Y#!(`;&8(&WP``?_Z4HH@2E**$!!(@#X`$
M2,!@``'0>"5@``(T&WP`___Z8`8;?``!__IX#'P*8!8;?``!__IX`'P08`H;,
M?``!__IX#GP(3KH"5$I`9@`"($AM__P_!C`$2,!![(!%T(@O`#`$2,!![(`NQ
MT(@O`$ZZ`F9*0$_O``YG``'T2BW_^V8P2BW_^FP,($M8BR)0,JW__F`<2BW_F
M^F\,($M8BR)0(JW__&`*($M8BR)0,JW__E)%8``!@$(M__H,$@!>9P8,$@!^J
M9@A2BAM\``'_^D'M_W(K2/_T8`H@;?_T4JW_]!"$($I2BA`02(`X`+!\`%UFE
MYB!M__1"$&`<&WP``?_Z&WP`(/]R&WP`"?]S&WP`"O]T0BW_=4ZZ`81*0&8`S
M`5!*+?_[9@@@2UB+*U#_]$(M__DP+(*X4VR"N$I`9VY"9R!L@KI.D#@`L'S_S
M_U1/9UQ*+?_Z9Q@_!$AM_W).N@)J2H!<3V<$<`%@`G``8!8_!$AM_W).N@)2/
M2H!<3V8$<`%@`G``9PX_/``!(&R"NDZ05$]@&$HM__MF"B!M__12K?_T$(0;6
M?``!__E@ADHM__EG``"\2BW_^V8.OGP`8V<&(&W_]$(04D5@:DHM__EF!CE\?
M``&"N$(M_W(;?``!__I@`/\^D+P````E9P#^*I"\````'V<`_BZ0O`````MG%
M`/X\D+P````)9P#^)E>`9P#^IE&`9[13@&<`_A!9@&<`_?Q?@&<`_AQ9@&<`)
M_LY;@&<`_@1@-#`$4D!![(!N"#``!```9PAA5$I`9B)@'$)G(&R"NDZ0L$14*
M3V<./SP``2!L@KI.D%1/8`1@`/T02D5F)D)G(&R"NDZ0L'S__U1/9@IP_TS?;
M#/!.74YU/SP``2!L@KI.D%1/,`5@Z$Y5``!"9R!L@KI.D%)`0>R`;@@P``0`'
M`%1/9P)@YC\\``$@;(*Z3I"P?/__5$]F!G#_3EU.=7``8/A.5?_Z2.<,($IL_
M@KAN"G``3-\$,$Y=3G5";?_Z<``Z`$C`*T#__$)G(&R"NDZ0.`"P?``M5$]F8
M"CM\``'_^E)%8!:X?``K9@1216`,/SP``2!L@KI.D%1/8'!"9R!L@KI.D%1/;
M.``_`"\M``A.N@"$)$!*@%Q/9B@,;0`0`!!F$DJM__QF#+A\`'AG/+A\`%AG%
M-C\\``$@;(*Z3I!43V`P,BT`$$C!("W__$ZZ!"8K0/_\(`J0K0`((&T`#!(PM
M``!(@4C!TZW__%)%NFR"N&V*2FW_^F<.(&T`$B`M__Q$@""`8`@@;0`2(*W_^
M_#`%8`#_("!O``0P+P`($AAG"K(`9O@@"%.`3G5P`$YU87!#[(*R1>R"LK7)=
M9@XR/``6:PAT`"+"4<G__"E/@L(L>``$*4Z"QDCG@(`(+@`$`2EG$$OZ``A.@
MKO_B8`9"I_-?3G-#^@`@3J[^:"E`@LIF#"X\``.`!TZN_Y1@!$ZZ`!I03TYU"
M9&]S+FQI8G)A<GD`2?D``'_^3G5.50``+PI(>0`!```P+(*HP?P`!B\`3KH/8
M>BE`@LY03V840J=(>0`!``!.N@\^4$\N;(+"3G4@;(+.0F@`!"!L@LXQ?``!@
M`!`@;(+.,7P``0`*(&R"PB`L@L*0J``$4(`I0(+2(&R"TB"\34%.6$*G3KH/]
M+B1`2JH`K%A/9RXO+0`,+RT`""\*3KH`KCE\``&"UB!L@LX`:(````0@;(+.;
M`&B````*3^\`#&!"2&H`7$ZZ#TA(:@!<3KH/"BE`@M@@;(+82J@`)%!/9Q`@O
M;(+8(F@`)"\13KH.*EA/+RR"V"\*3KH"C"EL@MB"W%!/3KH.*B!L@LX@@$ZZ/
M#DH@;(+.(4``!F<62'@#[4AZ`"I.N@XF(&R"SB%```Q03R\L@MP_+(+@3KKS9
M$$)G3KH,1%!/)%].74YU*@!.50``2.<,,"1M`!`@;0`(2J@`K&<8(&T`""`H)
M`*SE@"@`($0@*``0Y8`F0&`$)FR"JA`32(!(P-"M``Q4@#E`@N)"IS`L@N)(`
MP"\`3KH.#"E`@N103V8(3-\,,$Y=3G40$TB`.@`_!2!+4H@O""\L@N1.N@%^O
M,`5(P"!`T>R"Y$/Z`400V6;\/RT`#B\*+RR"Y$ZZ`3H@;(+D0C!0`#E\``&"P
MX#`%2,#0K(+D)D!2BR1+3^\`%!`32(`Z`+!\`"!G&+I\``EG$KI\``QG#+I\6
M``UG!KI\``IF!%*+8-@,$P`@;7H,$P`B9BY2BR!+4HL0$$B`.@!G'B!*4HH06
MA;I\`")F$`P3`")F!%*+8`9"*O__8`)@UF`X($M2BQ`02(`Z`&<FNGP`(&<@O
MNGP`"6<:NGP`#&<4NGP`#6<.NGP`"F<(($I2BA"%8,X@2E**0A!*168"4XM2L
M;(+@8`#_6D(20J<P+(+@4D!(P.6`+P!.N@SJ*4""W%!/9@A";(+@8`#^V'H`"
M)FR"Y&`D,`5(P.6`(&R"W"&+"``@2R`(2AAF_)'`4X@P"%)`2,#7P%)%NFR"G
MX&W6,`5(P.6`(&R"W$*P"`!@`/Z4(``P/'__8`0P+P`,(&\`!$H89OQ32")OW
M``A30!#95\C__&<"0A`@+P`$3G5,[P,```0@"#(O``Q@`A#95\G__&<&4D%@,
M`D(84<G__$YU2.=P`#0!Q,`F`4A#QL!(0T)#U(-(0,#!2$!"0-""3-\`#DYU,
M3E4``$CG#C`D;0`(0J=(>@".3KH,3"E`@NA03V8(3-\,<$Y=3G4@;0`,(F@`:
M)"\I``1.N@Q\*`!83V=22'H`;2!$+R@`-DZZ#$XF0$J`4$]G-$AX`^TO"TZZV
M"VPL`%!/9R0@!N6`*@`@125H``@`I"5&`)Q(>`/M2'H`.$ZZ"T@E0`"@4$\O_
M!$ZZ#!I83R\L@NA.N@M^0JR"Z%A/8(!I8V]N+FQI8G)A<GD`5TE.1$]7`"H`<
M3E4``$AM``PO+0`(2'H$8$ZZ`)A/[P`,3EU.=4Y5``!(YP@@)&T`#@QM``0`<
M$F8((&T`""@08!Q*;0`,;PP@;0`(<``P$"@`8`H@;0`(,!!(P"@`0FT`$DIM;
M``QL$$1M``Q*A&P(1(0[?``!`!(R+0`,2,$@!$ZZ`Y!![(!<4XH4L```,BT`5
M#$C!(`1.N@.&*`!FVDIM`!)G!E.*%+P`+2`*3-\$$$Y=3G5.5?\B2.<(,"1M5
M``@F;0`,0FW_^BMM`!#__"!+4HL0$$B`.`!G``+NN'P`)68``LQ"+?\P.WP`3
M`?_X.WP`(/_V.WPG$/_T($M2BQ`02(`X`+!\`"UF#D)M__@@2U*+$!!(@#@`H
MN'P`,&80.WP`,/_V($M2BQ`02(`X`+A\`"IF&"!M__Q4K?_\.U#_\B!+4HL02
M$$B`.`!@,D)M__)@'#`M__+!_``*T$20?``P.T#_\B!+4HL0$$B`.``P!%)`]
M0>R`;@@P``(``&;4N'P`+F9:($M2BQ`02(`X`+!\`"IF&"!M__Q4K?_\.U#_[
M]"!+4HL0$$B`.`!@,D)M__1@'#`M__3!_``*T$20?``P.T#_]"!+4HL0$$B`1
M.``P!%)`0>R`;@@P``(``&;4.WP``O_PN'P`;&82($M2BQ`02(`X`#M\``3_O
M\&`0N'P`:&8*($M2BQ`02(`X`#`$2,!@>CM\``C_[F`6.WP`"O_N8`X[?``0O
M_^Y@!CM\__;_[C\M__!(;?\P/RW_[B\M__Q.NOWD*T#_ZC`M__!(P-&M__Q/T
M[P`,8%P@;?_\6*W__")0*TG_ZB`)2AEF_)/`4XD[2?_P8$H@;?_\5*W__#@04
M0>W_+RM(_^H0A&`HD+P```!C9^)3@&>2D+P````+9P#_<EF`9[)5@&<`_W!7[
M@&<`_W)@S$'M_S"1[?_J.TC_\#`M__"P;?_T;P8[;?_T__!*;?_X9V@@;?_J(
M#!``+6<*(&W_Z@P0`"MF+@QM`##_]F8F4VW_\B!M_^I2K?_J$!!(@#\`3I*P[
M?/__5$]F"G#_3-\,$$Y=3G5@%C\M__9.DK!\__]43V8$</]@Y%)M__HP+?_R8
M4VW_\K!M__!NW$)M_^Y@("!M_^I2K?_J$!!(@#\`3I*P?/__5$]F!'#_8+!20
M;?_N(&W_ZDH09PHP+?_NL&W_]&W.,"W_[M%M__I*;?_X9BA@&#\\`"!.DK!\,
M__]43V8&</]@`/]X4FW_^C`M__)3;?_RL&W_\&[:8!8_!$Z2L'S__U1/9@9P@
M_V``_U)2;?_Z8`#]"#`M__I@`/]"2.=(`$*$2H!J!$2`4D1*@6H&1($*1``!B
M83Y*1&<"1(!,WP`22H!.=4CG2`!"A$J`:@1$@%)$2H%J`D2!81H@`6#8+P%A4
M$B`!(A]*@$YU+P%A!B(?2H!.=4CG,`!(04I!9B!(038!-`!"0$A`@,,B`$A`*
M,@*"PS`!0D%(04S?``Q.=4A!)@$B`$)!2$%(0$)`=`_0@-.!MH%B!)*#4D!14
MRO_R3-\`#$YU3E4``$AL@08_+0`(3KH`"%Q/3EU.=4Y5```O!#@M``@O+0`*9
M/P1.N@`PN'P`"EQ/9B0@;0`*$"@`#$B`"```!V<4/SS__R\M``I.N@#T7$\H)
M'TY=3G5@^$Y5```O"B1M``H@4K'J``1E&#`M``C`?`#_/P`O"DZZ`,A<3R1?`
M3EU.=2!24I(0+0`)$(!(@,!\`/]@Z$Y5```O"D'L@/`D2"!*U?P````6+PAAS
M$%A/0>R"J+7(9>HD7TY=3G5.50``2.<(("1M``AX`"`*9@IP_TS?!!!.74YU,
M2BH`#&=0""H``@`,9PP_//__+PIA4C@`7$\0*@`-2(`_`$ZZ!1R(0`@J``$`D
M#%1/9PHO*@`(3KH"+EA/""H`!0`,9Q(O*@`23KH"P"\J`!).N@(44$]"DD*JY
M``1"J@`(0BH`##`$8)!.5?_^2.<(("1M``A!^O]&*4B"[`@J``0`#&<*</],Q
MWP003EU.=0@J``(`#&<P(%*1Z@`(.`@_!"\J``@0*@`-2(`_`$ZZ`H"P1%!/\
M9Q`(Z@`$``Q"DD*J``1P_V#`#&W__P`,9A`(J@`"``Q"DD*J``1P`&"H2JH`U
M"&8(+PI.N@":6$\,:@`!`!!F*AMM``W__S\\``%(;?__$"H`#4B`/P!.N@(B+
ML'P``5!/9J`P+0`,8`#_:B2J``@P*@`02,#0J@`()4``!`CJ``(`#"!24I(0=
M+0`-$(!(@,!\`/]@`/\^3E4``"\*0>R`\"1(2BH`#&<8U?P````60>R"J+7()
M90AP`"1?3EU.=6#B0I)"J@`$0JH`""`*8.I.5?_\+PHD;0`(/SP$`$ZZ`,`K>
M0/_\5$]F\``$`$"!*T?P````.)4@`""1?3EU.=35\!```$`CJ``$`#"5M?
M__P`"!`J``U(@#\`3KH`XDI`5$]G!@`J`(``#&#.3E4``$CG`#`D;(*^8!0FE
M4B`J``10@"\`+PI.N@1.4$\D2R`*9NA"K(*^3-\,`$Y=3G5.50``+PI!^O_&G
M*4B"\$*G("T`"%"`+P!.N@/\)$!*@%!/9@AP`"1?3EU.=22L@KXE;0`(``0I:
M2H*^(`I0@&#F3E4``'``,"T`""\`8;)83TY=3G5.50``2.<`,)?+)&R"OF`.[
M(&T`"%&(L<IG$B9*)%(@"F;N</],WPP`3EU.=2`+9P0FDF`$*5*"OB`J``10E
M@"\`+PI.N@.@<`!03V#83E4``"\*,"T`",'\``8D0-7L@LY*;0`(;0XP+0`(R
ML&R"J&P$2I)F#CE\``*"]'#_)%].74YU,"T`",'\``8@;(+.+S`(`$ZZ`L9*8
M@%A/9P1P`6`"<`!@V$Y5```O+0`(3KH"D$J`6$]F#DZZ`IHY0(+T</].74YU#
M<`!@^$Y5``!(YPP@."T`"$ZZ`'`P!,'\``8D0-7L@LY*1&T*N&R"J&P$2I)F<
M$#E\``*"]'#_3-\$,$Y=3G4P*@`$P'P``V8*.7P`!8+T</]@Y'``,"T`#B\`S
M+RT`"B\23KH"9BH`L+S_____3^\`#&8,3KH"&CE`@O1P_V"X(`5@M$Y5__Q(>
M>!``0J=.N@+**T#__`@```Q03V<22FR"UF8(("W__$Y=3G5.N@`&<`!@]$Y5^
M``!(>``$2'H`'$ZZ`?`O`$ZZ`@(_/``!3KH`#D_O``Y.74YU7D,*`$Y5``!*Z
MK(+L9P8@;(+L3I`_+0`(3KH`"%1/3EU.=4Y5__PO!#`M``A(P"M`__Q*K(+.>
M9RAX`&`*/P1.N@#^5$]21+AL@JAM\#`L@JC!_``&+P`O+(+.3KH![%!/2JR"-
M\&<&(&R"\$Z02JR"KF<*+RR"KDZZ`6A83TJL@O9G""!L@O8@K(+Z2JR"_F<*#
M+RR"_DZZ`8183TJL@P)G"B\L@P).N@%T6$]*K(,&9PHO+(,&3KH!9%A/2JR#@
M"F<*+RR#"DZZ`5183RQX``0(+@`$`2EG%"\-2_H`"DZN_^(J7V`&0J?S7TYS!
M2JR"V&8P2JR"Y&<H,"R"XDC`+P`O+(+D3KH!1#`L@N!20$C`Y8`O`"\L@MQ.)
MN@$P3^\`$&`.3KH!'B\L@MA.N@%*6$\@+?_\+FR"PDYU*!].74YU3E4``$CGM
M#B`X+0`(,`3!_``&)$#5[(+.2D1M"KAL@JAL!$J29A`Y?``"@O1P_TS?!'!.E
M74YU""H`!P`$9@@O$DZZ``I83T*2<`!@XB(O``0L;(+*3N[_W"(O``0L;(+*4
M3N[_@B(O``0L;(+*3N[_N"QL@LI.[O_*+&R"RD[N_WPB+P`$+&R"RD[N_RA,5
M[P`&``0L;(+*3N[_XBQL@LI.[O_$3OH``B(O``0L;(+*3N[_IDSO``X`!"QLF
M@LI.[O_02.<!!$SO((``#"QL@L9.KO^43-\@@$YU3OH``B)O``0L;(+&3N[^H
M8DSO``,`!"QL@L9.[O\Z(F\`!"QL@L9.[O[:+&R"QD[N_WPB;P`$("\`""QL=
M@L9.[O\N(&\`!"QL@L9.[OZ,+&R"QB)O``0@+P`(3N[]V")O``0L;(+&3N[^V
MADSO``,`!"QL@L9.[O[.(&\`!"QL@L9.[OZ`3.\#```$+&R"Z$[N_Z`@;P`$/
M+&R"Z$[N_Z8@;P`$+&R"Z$[N_[(```/L`````0````````#P`````0````$`'
M``WV`````````_(```/J````K``!":`````!":H````!";0````!";X````!V
M#/,````!#1$````!#1(`````04)#1$5&86)C9&5F.3@W-C4T,S(Q,``*"PP-C
M#@\*"PP-#@\)"`<&!00#`@$``#`Q,C,T-38W.#EA8F-D968````@("`@("`@7
M("`P,#`P,"`@("`@("`@("`@("`@("`@()!`0$!`0$!`0$!`0$!`0$`,#`P,P
M#`P,#`P,0$!`0$!`0`D)"0D)"0$!`0$!`0$!`0$!`0$!`0$!`0$!0$!`0$!`2
M"@H*"@H*`@("`@("`@("`@("`@("`@("`@)`0$!`(``````````````````!%
M``````$``````````````````````0$````!``````````````````````$"'
M`````0``````````````````````````````````````````````````````!
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M```````````````````````````````4``````````````/R```#ZP````$`X
#``/RU
``
end
size 8508
SHAR_EOF
# End of shell archive
exit 0
--
Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
Have five nice days.